using System;
using System.Collections.Generic;
using System.Text;
using it.mintlab.desktopnet.mintar;
using System.Net;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.IO;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Converters;

namespace it.mintlab.desktopnet.health360.server
{
    public class CRUDWebRequest : WebRequest
    {
        public const string OPERATION_INSERT = "insert";
        public const string OPERATION_INSERT_IDENTITY = "insertIdentity";
        public const string OPERATION_SELECT = "select";
        public const string OPERATION_SELECT_BY_FILTER = "selectByFilter";
        public const string OPERATION_SELECT_BY_KEY = "selectByKey";
        public const string OPERATION_UPDATE_BY_KEY = "updateByKey";
        public const string OPERATION_DELETE_BY_KEY = "deleteByKey";

        private Model model;
        private String sqlFilter;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="model"></param>
        /// <param name="crudType"></param>
        public CRUDWebRequest(Model model, String operation)
        {
            this.model = model;
            this.Operation = operation;
        }
        
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="model">model</param>
        /// <param name="operation">operation</param>
        /// <param name="customSQL">sql filter (WHERE..)</param>
        public CRUDWebRequest(Model model, String operation, String sqlFilter)
        {
            this.model = model;
            this.Operation = operation;
            this.sqlFilter = sqlFilter;
        }

        /// <summary>
        /// execute crud on DB and return JSON result string
        /// </summary>
        /// <returns>JSON string result</returns>
        public string serveJSON()
        {
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            using (JsonWriter jsonWriter = new JsonTextWriter(sw))
            {
                jsonWriter.Formatting = Formatting.Indented;
                jsonWriter.WriteStartObject();
                jsonWriter.WritePropertyName("crudResponse");
                jsonWriter.WriteStartObject();
                jsonWriter.WritePropertyName("operation");
                jsonWriter.WriteValue(Operation);
                jsonWriter.WritePropertyName("modelType");
                string modelType = model.GetType().AssemblyQualifiedName;
                jsonWriter.WriteValue(modelType.Substring(0, modelType.IndexOf(',', modelType.IndexOf(',') + 1)));
                jsonWriter.WritePropertyName("result");

                JsonSerializerSettings settings = new JsonSerializerSettings();
                settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                IsoDateTimeConverter isoDateTimeConverter = new IsoDateTimeConverter();
                isoDateTimeConverter.DateTimeFormat = "yyyy-MM-ddTHH\\:mm\\:ss";
                settings.Converters.Add(isoDateTimeConverter);
                // serve crud operation
                switch (Operation)
                {
                    case CRUDWebRequest.OPERATION_INSERT:
                        if (model.insert())
                            jsonWriter.WriteRaw(JsonConvert.SerializeObject(model, Formatting.Indented, settings));
                        else // return an empty object
                            jsonWriter.WriteRaw(JsonConvert.SerializeObject(null, Formatting.Indented, settings));
                        break;
                    case CRUDWebRequest.OPERATION_INSERT_IDENTITY:
                        model.insertIdentity();
                        jsonWriter.WriteRaw(JsonConvert.SerializeObject(model, Formatting.Indented, settings));
                        break;
                    case CRUDWebRequest.OPERATION_SELECT:
                        jsonWriter.WriteRaw(JsonConvert.SerializeObject(model.select(),Formatting.Indented, settings));
                        break;
                    case CRUDWebRequest.OPERATION_SELECT_BY_KEY:
                        if(model.selectByKey())
                            jsonWriter.WriteRaw(JsonConvert.SerializeObject(model, Formatting.Indented, settings));
                        else // return an empty object
                            jsonWriter.WriteRaw(JsonConvert.SerializeObject(Model.createModel(Type.GetType(modelType)) , Formatting.Indented, settings));
                        break;
                    case CRUDWebRequest.OPERATION_UPDATE_BY_KEY:
                        if (model.updateByKey())
                            jsonWriter.WriteRaw(JsonConvert.SerializeObject(model, Formatting.Indented, settings));
                        else // return an empty object
                            jsonWriter.WriteRaw(JsonConvert.SerializeObject(null, Formatting.Indented, settings));
                        break;
                    case CRUDWebRequest.OPERATION_DELETE_BY_KEY:
                        if (model.deleteByKey())
                            jsonWriter.WriteRaw(JsonConvert.SerializeObject(model, Formatting.Indented, settings));
                        else // return an empty object
                            jsonWriter.WriteRaw(JsonConvert.SerializeObject(null, Formatting.Indented, settings));
                        break;
                    case CRUDWebRequest.OPERATION_SELECT_BY_FILTER:
                        jsonWriter.WriteRaw(JsonConvert.SerializeObject(model.selectByFilter(this.sqlFilter), Formatting.Indented, settings));
                        break;
                    default:
                        return "";
                }
                jsonWriter.WriteEndObject();
                jsonWriter.WriteEndObject();
                jsonWriter.Flush();
            }
            return sb.ToString();
        }

    }
}
